﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Downplay.Alchemy.Dynamic;

namespace Downplay.Alchemy.Tests.Dynamics {
    [TestFixture]
    public class XmlTests {

        [Test]
        public void CanSerializeToXml() {
            dynamic stuff = new Stuff();
            Assert.That((string)stuff.Xml().ToString(), Is.EqualTo("<Null />"));
            stuff.Foo = "Bar";
            Assert.That(stuff.Xml().ToString(), Is.EqualTo("<Object>\r\n  <Foo>Bar</Foo>\r\n</Object>"));
            stuff.Foo.Metadata.XmlAttribute = true;
            Assert.That(stuff.Xml().ToString(), Is.EqualTo("<Object Foo=\"Bar\" />"));
        }

        [Test]
        public void CanDeserializeXmlSettings() {
            // From Media Garden
            var test = "<settings ContentLength=\"4123123123123\" MimeType=\"\" Title=\"DSCN4876\" SourceName=\"MediaFormat\" SizeX=\"1200\" SizeY=\"1600\" />";
            dynamic stuff = new Stuff();
            stuff.Xml(test);
            Assert.That((string)stuff.SourceName, Is.EqualTo("MediaFormat"));
            Assert.That((long)stuff.ContentLength, Is.EqualTo(4123123123123));
            Assert.That((int)stuff.SizeX, Is.EqualTo(1200));
        }

        [Test]
        public void CanDeserializeFromXmlNodes() {
            dynamic stuff = new Stuff();
            stuff.Xml("<Stuff><Foo>Bar</Foo></Stuff>");
            Assert.That(stuff.Json(), Is.EqualTo("{\"Foo\":\"Bar\"}"));
            Assert.That(stuff.Xml().ToString(), Is.EqualTo("<Stuff><Foo>Bar</Foo></Stuff>"));
            Assert.That((string)stuff.Foo, Is.EqualTo("Bar"));
            Assert.That((string)stuff.Supertype(), Is.EqualTo("Stuff"));
            Assert.That((string)stuff.Foo.Supertype(), Is.EqualTo("Value"));
            Assert.That((string)stuff.Foo.Stereotype(), Is.EqualTo("String"));
            Assert.That((bool)stuff.Foo.Metadata.XmlAttribute, Is.EqualTo(false));
        }
        [Test]
        public void CanDeserializeFromXmlAttributes() {
            dynamic stuff = new Stuff();
            stuff.Xml("<Stuff Foo=\"Bar\" />");
            Assert.That((string)stuff.Foo, Is.EqualTo("Bar"));
            Assert.That((string)stuff.Supertype(), Is.EqualTo("Stuff"));
            Assert.That((string)stuff.Foo.Supertype(), Is.EqualTo("Value"));
            Assert.That((string)stuff.Foo.Stereotype(), Is.EqualTo("String"));
            Assert.That((bool)stuff.Foo.Metadata.XmlAttribute, Is.EqualTo(true));
        }


        [Test]
        public void CanAccessXmlNodesAndAttributes() {
            string xml = "<Root><Foo Bar=\"Car\"><Bar>Zar</Bar></Foo></Root>";
            dynamic stuff = new Stuff();
            stuff.Xml(xml);

            Assert.That((string)stuff.Supertype(), Is.EqualTo("Root"));
            Assert.That((string)stuff.Foo.Supertype(), Is.EqualTo("Foo"));
            // XML nodes by array access
            Assert.That((string)stuff[0].Supertype(), Is.EqualTo("Foo"));
            // XML attributes take precedence
            Assert.That((string)stuff.Foo.Bar, Is.EqualTo("Car"));
            // But can access node
            Assert.That((string)stuff.Foo[0], Is.EqualTo("Zar"));
            // By member
            Assert.That((string)stuff.Foo.Nodes.Bar, Is.EqualTo("Zar"));
            // By indexer
            Assert.That((string)stuff.Foo.Nodes["Bar"], Is.EqualTo("Zar"));
        }

        [Test]
        public void CanAccessXmlNodesWhenNamedAttributeExists() {
            // Slightly different test
            string xml = "<Root><Foo Bar=\"Car\"><Bar Far=\"Har\"><Who>You</Who></Bar></Foo></Root>";
            dynamic stuff = new Stuff();
            stuff.Xml(xml);

            // Here there's an attribute called Bar but because we access child properties, we know it *has* to be the node we're after
            Assert.That((string)stuff.Foo.Bar.Far, Is.EqualTo("Har"));
            // Accessing a child node should also be fine
            Assert.That((string)stuff.Foo.Bar.Who, Is.EqualTo("You"));
        }


    }
}
